package qcurepay

import (
	"fmt"
	"bytes"
	"sort"
	"strings"
	"crypto/md5"
	"io/ioutil"
	"net/http"
	"encoding/json"
	"thirdpaysdk/utils/mapstruct"
	"github.com/pkg/errors"
)

type Auth struct {
	merchanNo   string
	AppSecret   string
	requrl      string
}

func NewSDK(restURL, appsecret string) *Auth {
	return &Auth{requrl: restURL, AppSecret: appsecret}
}

func (this *Auth) Request(request interface{}) (respMap map[string]interface{}, err error) {
	reqParams := mapstruct.Struct2Map(request, "json")
	reqParams["sign"] = MakeSign(reqParams, this.AppSecret)
	var (
		req   *http.Request
		body  []byte
	)
	client := &http.Client{}
	body, err = json.Marshal(reqParams)
	if err != nil {
		return
	}
	fmt.Println("req body:", string(body))
	req, err = http.NewRequest("POST", this.requrl, bytes.NewBuffer(body))
	if err != nil {
		return
	}
	//req.Header.Set("Content-Type", "application/x-www-form-urlencoded") //必须
	resp, err := client.Do(req)
	if err != nil {
		return
	}
	//resCode = resp.StatusCode
	defer resp.Body.Close()
	bodyBytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}
	fmt.Println("rsp body:", string(bodyBytes))
	err = json.Unmarshal(bodyBytes, &respMap)
	if err != nil {
		err = errors.New(fmt.Sprintf("%s %s", err.Error(), string(bodyBytes)))
	}
	return
}

// 生成sign
func MakeSign(params map[string]interface{}, key string) string {
	paramsNew := make(map[string]string)
	for k, v := range params {
		paramsNew[k] = fmt.Sprintf("%v", v)
	}
	var keys []string
	var sorted []string
	for k, v := range paramsNew {
		if k != "sign" && v != "" {
			keys = append(keys, k)
		}
	}
	sort.Strings(keys)
	for _, k := range keys {
		sorted = append(sorted, fmt.Sprintf("%s=%s", k, paramsNew[k]))
	}
	str := strings.Join(sorted, "&")
	str += "&" + key
	return fmt.Sprintf("%X", md5.Sum([]byte(str)))
}
